<template>
  <div>
    <div class="mapClass" id="container" :style="{width: width+'%', height: height+ 'px'}">
      <div class="listCar" v-if="carList_props.length!==0">
          <virtual-list  :size="70" :remain="8">
            <draggable v-model="carList_props" v-bind="dragOptions" @start="drag = true" @end="drag = false">
              <transition-group type="transition" :name="!drag ? 'flip-list' : null">
                <div v-for="(element,index) in carList_props" :key="element.id" class="car" v-show="index!=0">
                  <div>运载顺序：{{element.sort}}</div>
                  <div>取货地址: {{element.loadaddressDetails}}</div>
                  <div>卸货地址：{{element.addressDetails}}</div>
                  <div>包裹编号: <span v-for="(item,index) in element.wraps" :key="index">{{item+','}}</span></div>
                </div>
              </transition-group>
          </draggable>
          </virtual-list>
      </div>
      <slot name='buttonFooter'></slot>
      <div class="listCar" v-if="myArray.length!==0">
          <virtual-list  :size="70" :remain="8">
            <draggable v-model="myArray" v-bind="dragOptions" @start="drag = true" @end="drag = false">
              <transition-group type="transition" :name="!drag ? 'flip-list' : null">
                <div v-for="element in myArray" :key="element.id" class="car">
                  <div>车次编号(运单编号): {{ element.waybillNum}}</div>
                  <div>取货地址: {{ element.startAddress}}</div>
                  <div>终点地址: {{ element.endAddress}}</div>
                  <div>司机信息: {{ element.name + element.mobile }}</div>
                  <div>车牌号: {{ element.licensePlate }}</div>
                </div>
              </transition-group>
          </draggable>
          </virtual-list>
      </div>
    </div>
  </div>
</template>
<script>
// 高性能列表解决方案
import virtualList from 'vue-virtual-scroll-list'
// 高性能拖拽方案
import draggable from 'vuedraggable'
// /**
//  * 防抖方法
//  */
// const debounce = (fn, wait=500) =>{
//   return function() {
//     clearTimeout(fn.timer)
//     fn.timer = setTimeout(fn.bind(this, ...arguments), wait)
//   }
// }
export default {
  props: {
    /**
     * common.vue
     */
    carList_c: {
      type: Array,
      default: () => {
        return []
      }
    },
    /**
     * common.vue
     */
    carDetail_c: {
      type: Object,
      default: () => {
        return {
          car: 'AP0000',
          longitude: 121.393459,
          latitude: 31.315814,
          leaveEndlng: 121.393459,
          leaveEndlat: 31.315814,
          arrivelng: 121.407618,
          arrivelat: 31.297850,
        }
      }
    },
    carList: {
      type: Array,
      default: () => {
        return []
      }
    },
    carDetail: {
      type: Object,
      default: () => {
        return {}
      }
    },
    width: {
      type: Number,
      default: 100
    },
    height: {
      type: Number,
      default: 600,
    }
  },
  components: { 'virtual-list': virtualList, draggable },
  data() {
    return {
      drag: false,
      myArray: [],
      cluster: null,
      map: null,
      newViewData: {},
      overLayGroup: [],
      drivingId: null, // 路线规划
      cc: null,
      passedPolyline: null,
      indexOne: null, // 当前选择那个辆车的key
      car: null, // 当前运动的car 🚗
      carList_props: this.carList_c,
      carIconFuel: null
    }
  },
  computed: {
    carDataObj0() { // 从后台获取的数据-----小汽车
      return this.carList.map(x => {
        return {
          car: x.licensePlate,
          longitude: x.nowLongitude,
          latitude: x.nowLatitude,
          type: x.truckType,
          truckId: x.truckId
        }
      })
    },
    dragOptions() {
      return {
        animation: 200,
        group: "description",
        disabled: false,
        ghostClass: "ghost"
      };
    }
  },
  watch: {
    carDataObj0: {
      immediate: true,
      handler(newVal,oldVal) {
        if (newVal) {
          this.$nextTick(() => {
            this.computeMarkers()
          })
        }
      }
    },
    carDetail: {
      immediate: true,
      handler(newVal,oldVal) {
        if(newVal&&newVal.waybillAddressSet) {
          this.myArray = []
          this.myArray.push(newVal);
          (async () => {
            await this.driving(newVal.waybillAddressSet)
            await this.polyline(this.overLayGroup.Pw[this.indexOne],newVal.positionList)
          })();
        }
      }
    },
    carList_props: {
      immediate: true,
      handler(newVal) {
        if (newVal) this.$store.commit('carList_props', newVal)
      }
    }
  },
  mounted() {
    this.map = new AMap.Map("container", {
      resizeEnable: true,
      center: [121.48107,31.229365],
      zoom: 12
    })
    // 创建一个 icon
    this.carIconFuel = new AMap.Icon({
      size: new AMap.Size(64, 64),
      image: 'https://img.icons8.com/dusk/64/000000/car.png',
      imageSize: new AMap.Size(32, 32)
      // imageOffset: new AMap.Pixel(-95, -3)
    })
    this.reloadMarks()
  },
  created() {
    this.$on('_driving',() => {
      this.preview()
    })
  },
  destroyed() {
    this.map && this.map.destroy()
  },
  methods: {
    /**
     * 预览
     */
    preview() {
      this.driving(this.carList_props)
    },
    /**
     * 返回
     */
    goBack() {
      this.$emit('goBack', this.carList_props)
    },
    /**
     * 驾车🚗
     */
    driving(waybillAddressSet) {
      if(this.drivingId) this.drivingId.clear() // 删除驾车规划
      let point = waybillAddressSet.map(x => {
        return [x.longitude,x.latitude]
      })
      const start = point.shift();
      const end = point.pop();
      return new Promise((resolve,reject) => {
        AMap.plugin(['AMap.Driving'], () => {
          this.drivingId = new AMap.Driving({
            map: this.map,
          });//驾车路线规划
          this.drivingId.clear()
          this.drivingId.search(start,end,{waypoints: point},(status, result) => {
            // result 即是对应的驾车导航信息，相关数据结构文档请参考
            if (status === 'complete') {
              console.log('绘制驾车路线完成')
              resolve()
            } else {
              this.$notify.error({
                title: '错误',
                message: '获取驾车数据失败：' + result
              });
            }
          })
        })
      })
    },
    /**
     * 绘制当前的形成路线
     */
    polyline(car, positionList) {
      // 轨迹回放点
      let lineArr = positionList.map(x => {
        return [x.longitude,x.latitude]
      })
      return new Promise((resolve,reject) => {
        AMap.plugin(['AMap.Polyline'], () => {
          // 绘制轨迹
          this.cc = new AMap.Polyline({
            map: this.map,
            path: lineArr,
            showDir:true,
            strokeColor: "#28F",  //线颜色
            strokeOpacity: 0,     //线透明度
            strokeWeight: 6,      //线宽
            // strokeStyle: "solid"  //线样式
          });
          this.passedPolyline = new AMap.Polyline({
            map: this.map,
            // path: lineArr,
            strokeColor: "#AF5",  //线颜色
            // strokeOpacity: 1,     //线透明度
            strokeWeight: 6,      //线宽
            // strokeStyle: "solid"  //线样式
          });
          car.on('moving', (e) => {
            this.passedPolyline.setPath(e.passedPath);
          })
          car.moveAlong(lineArr, 2000)
          this.car = car
        })
      })
    },
    /**
     * setPosition 设置当前位置
     * setIcon 设置当前的icon
     */
    setPosition(car,longitude,latitude) {
      // if(car === "FUEL") {
        return new AMap.Marker({
          position: new AMap.LngLat(longitude,latitude),
          icon: this.carIconFuel,
          offset: new AMap.Pixel(-13, -30)
        })
      // }
    },
    /**监听地图拖拽，放大事件，根据屏幕范围动态渲染点位 */
    reloadMarks() {
      AMap.event.addListener(this.map,'moveend',()=> {
        this.computeMarkers();
      })
      AMap.event.addListener(this.map,'zoomend',()=> {
        this.computeMarkers();
      })
      AMap.event.addListener(this.map,'resize',()=> {
        this.computeMarkers();
      })
    },
    /** 根据当前屏幕范围筛选marker */
    computeMarkers() {
      this.newViewData={};
      //获取当前视图范围
      let now_bounds = this.map.getBounds();
      //遍历车辆数据，为了减少后台传入的重复数据，我的车辆信息列表一直使用对象保存
      this.carDataObj0.forEach(x => {
        if(now_bounds.contains(new AMap.LngLat(x.longitude, x.latitude))){
          //将当前屏幕内的视图点保存
          this.newViewData[x.car] = x ; // {type: 'car'}
        }
      });
      this.renderMarker();
      now_bounds = null;
    },
    /** 创建聚合**/
    createCluser(markerArr) {
      AMap.plugin(['AMap.MarkerClusterer'], () => {
        this.cluster = new AMap.MarkerClusterer(this.map, markerArr, {
          gridSize: 80,
          renderCluserMarker: this._renderClusterMarker,
          minClusterSize: 1,
          maxZoom: 18
        });
      })
    },
    /**
     * 绘制聚合物
     */
    _renderClusterMarker(context) {
      // var factor = Math.pow(context.count / count, 1 / 18);
      // var div = document.createElement('div');
      // var Hue = 180 - factor * 180;
      // var bgColor = 'hsla(' + Hue + ',100%,50%,0.7)';
      // var fontColor = 'hsla(' + Hue + ',100%,20%,1)';
      // var borderColor = 'hsla(' + Hue + ',100%,40%,1)';
      // var shadowColor = 'hsla(' + Hue + ',100%,50%,1)';
      // div.style.backgroundColor = bgColor;
      // var size = Math.round(30 + Math.pow(context.count / count, 1 / 5) * 20);
      // div.style.width = div.style.height = size + 'px';
      // div.style.border = 'solid 1px ' + borderColor;
      // div.style.borderRadius = size / 2 + 'px';
      // div.style.boxShadow = '0 0 1px ' + shadowColor;
      // div.innerHTML = context.count;
      // div.style.lineHeight = size + 'px';
      // div.style.color = fontColor;
      // div.style.fontSize = '14px';
      // div.style.textAlign = 'center';
      // context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2));
      // context.marker.setContent(div)
    },
    /** 将markers渲染到map上 */
    renderMarker() {
      //判断目前是否有当前覆盖物组
      this.overLayGroup = new AMap.OverlayGroup([])
      let MarkerAddArr = [];
      for(let y in this.newViewData){
        /**
         * 我的所有创建的Marker点对象都是长期存在于this.markerObj中，并不销毁，每次数据更
         * 新后调用marker对象的setPosition(),setAngle(),setIcon()等方法改变状态，再筛选出
         * 需要挂载上的一起加到地图上
        **/
        const x = this.newViewData[y].type // type 当前车是什么类型的车
        const lng = this.newViewData[y].longitude
        const lat = this.newViewData[y].latitude
        if(this.setPosition(x,lng,lat)){
          MarkerAddArr.push(this.setPosition(x,lng,lat))
        }
      }
      // 清除当前地铁图上的所有覆盖物，包括窗口、marker和线路。
      this.overLayGroup.clearOverlays();
      //超过200个点则开启聚合模式  且在聚合模式下不渲染面板展示点
      // if(MarkerAddArr.length >= 100 ){
      //   if(this.cluster){
      //     // 从地图上彻底清除所有聚合点标记
      //     this.cluster.clearMarkers()
      //     this.cluster.setMarkers(MarkerAddArr)
      //   }else{
      //     // 创造聚合物
      //     this.createCluser(MarkerAddArr)
      //   }
      // }else{
        if(this.cluster){
          this.cluster.clearMarkers()
        }
        // 添加多个覆盖物
        this.overLayGroup.addOverlays(MarkerAddArr)
        // 指定集合中里覆盖物的显示地图
        this.overLayGroup.setMap(this.map)
        // this.map.setFitView();
        // 返回当前集合中所有的覆盖物---给每个覆盖物添加点击事件
        this.overLayGroup.getOverlays().forEach((car,index) => {
          car.on('click', async (r) => {
            this.$emit('detail', this.carDataObj0[index].truckId)
            if(this.drivingId) this.drivingId.clear() // 删除驾车规划
            if(this.cc && this.passedPolyline && this.car) this.map.remove([this.cc,this.passedPolyline,this.car]) // 删除路径和小汽车
            this.indexOne = index
          })
        })
      // }
      MarkerAddArr = null;
    }
  }
}
</script>
<style scoped lang='scss'>
#container {
  width: 100%;
  height: 100vh;
  position: relative;
}
.listCar {
  background: gray;
  width: 300px;
  position: absolute;
  right: 0;
  top: 0;
  z-index: 1;
}
.flip-list-move {
  transition: transform 0.5s;
}
.no-move {
  transition: transform 0s;
}
.car {
  margin-bottom: 20px;
  cursor: move;
  width: 300px;
  border: 1px solid black;
  background: white;
  display: flex;
  justify-content: flex-start;
  flex-direction: column;
  box-sizing: border-box;
  padding-left: 20px;
  padding-top: 15px;
  padding-bottom: 15px;
  align-items: flex-start;
}
</style>
